package com.zb.security;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

/**
 * 在这种方法中,需要与configAttributes比较验证
 * 1、一个对象是一个URL,一个过滤器被这个URL找到权限配置,并通过这里
 * 2、如果没有匹配相应的认证,AccessDeniedException
 * 
 * @author zhoubang
 */
public class MyAccessDecisionManager implements AccessDecisionManager {

    /**
     * 在这个类中，最重要的是decide方法，如果不存在对该资源的定义，直接放行； 否则，如果找到正确的角色，即认为拥有权限，并放行，否则throw
     * new AccessDeniedException("no right");这样，就会进入上面提到的/accessDenied.jsp页面。
     */
    @Override
    public void decide(Authentication authentication, Object object,
            Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        // 资源所需的角色列表，如果角色列表为空，说明不需要对该资源进行拦截，放行！
        if (configAttributes == null) {
            return;
        }
        // 即将访问的资源URL,如 : /admin.jsp
        System.out.println(object.toString());// object is a URL.
        // 遍历所需的角色集合
        Iterator<ConfigAttribute> ite = configAttributes.iterator();
        while (ite.hasNext()) {
            ConfigAttribute ca = ite.next();
            // 该资源所需要的角色
            String needRole = ((SecurityConfig) ca).getAttribute();
            // authentication.getAuthorities()获取用户所拥有的角色列表,如：ROLE_ADMIN,ROLE_USER
            for (GrantedAuthority grantedAuthority : authentication
                    .getAuthorities()) {
                // 将资源所需要的角色与用户拥有的角色比较
                if (needRole.equals(grantedAuthority.getAuthority())) {// grantedAuthority
                                                                       // is
                                                                       // user's
                                                                       // role.
                    // 角色相同，直接放行
                    return;
                }
            }
        }
        // 否则，提示没有权限访问该资源
        throw new AccessDeniedException("no right");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

}
